/****************************************************************************
 *
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.  The
 * ASF licenses this file to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance with the
 * License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
 * License for the specific language governing permissions and limitations
 * under the License.
 *
 ****************************************************************************/

 /****************************************************************************
  * Included Files
  ****************************************************************************/

#include "FreeRTOS.h"
#include "task.h"
#include "timers.h"

#include <lwip/tcpip.h>
#include <lwip/sockets.h>
#include <lwip/netdb.h>

#include "bl_fw_api.h"
#include "wifi_mgmr_ext.h"
#include "wifi_mgmr.h"

#include "bflb_irq.h"
#include "bflb_uart.h"

#include "bl616_glb.h"
#include "rfparam_adapter.h"

#include "board.h"
#include "shell.h"

#include "storage.h"

  // #include "auadc.h"
  // #include "audac.h"

#define DBG_TAG "MAIN"
#include "log.h"
#include "stdint.h"
#include "storage.h"

#define USER_AP_NAME "Ai-M61-32s"
#define USER_AP_PASSWORD "123456789"

/****************************************************************************
 * Pre-processor Definitions
 ****************************************************************************/

#define WIFI_STACK_SIZE  (1536)
#define TASK_PRIORITY_FW (16)


 /****************************************************************************
  * Private Types
  ****************************************************************************/

  /****************************************************************************
   * Private Data
   ****************************************************************************/

static struct bflb_device_s* uart0;
static struct bflb_device_s* gpio;

static TaskHandle_t wifi_fw_task;

static wifi_conf_t conf = {
    .country_code = "CN",
};

extern void shell_init_with_task(struct bflb_device_s* shell);

/****************************************************************************
 * Private Function Prototypes
 ****************************************************************************/

 /****************************************************************************
  * Functions
  ****************************************************************************/

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

#include <FreeRTOS.h>
#include <task.h>
#include <queue.h>
#include <semphr.h>
#include <timers.h>
#include "wifi_event.h"

#define WIFI_HTTP_SERVER_STACK_SIZE  (1024 * 5)
#define HTTP_SERVERTASK_PRIORITY (15)

static TaskHandle_t http_server_task_hd;
void* MuxSem_Handle = NULL;

static void start_ap(void)
{
    wifi_mgmr_ap_params_t config = { 0 };
    // 通道
    config.channel = 3;
    // 设置AP热点名称
    config.ssid = USER_AP_NAME;
    // 设置密码
    config.key = USER_AP_PASSWORD;
    // 启动dhcp
    config.use_dhcpd = 1;

    // 设置最大连接数
    if (wifi_mgmr_conf_max_sta(2) != 0) {
        return 5;
    }
    // 启动AP模式
    if (wifi_mgmr_ap_start(&config) == 0) {
        return 0;
    }
}

void http_server_task(void* param)
{
    // 打开AP
    start_ap();
    // 启动http服务，也就是响应网页的服务
    mhttp_server_init();
}

void create_http_server_task(void)
{
    MuxSem_Handle = xSemaphoreCreateMutex();
    if (NULL != MuxSem_Handle)
    {
        printf("MuxSem_Handle creat success!\r\n");
    }

    xTaskCreate(http_server_task, (char*)"fw", WIFI_HTTP_SERVER_STACK_SIZE, NULL, HTTP_SERVERTASK_PRIORITY, &http_server_task_hd);
}

//fatfs
#include "fatfs_diskio_register.h"
#include "ff.h"

FATFS fs;
__attribute((aligned(8))) static uint32_t workbuf[4096];

MKFS_PARM fs_para = {
    .fmt = FM_FAT32,     /* Format option (FM_FAT, FM_FAT32, FM_EXFAT and FM_SFD) */
    .n_fat = 1,          /* Number of FATs */
    .align = 0,          /* Data area alignment (sector) */
    .n_root = 1,         /* Number of root directory entries */
    .au_size = 512 * 32, /* Cluster size (byte) */
};

void filesystem_init(void)
{
    FRESULT ret;

    board_sdh_gpio_init();

    fatfs_sdh_driver_register();

    ret = f_mount(&fs, "/sd", 1);
    // ret = FR_NO_FILESYSTEM;

    if (ret == FR_NO_FILESYSTEM) {
        LOG_W("No filesystem yet, try to be formatted...\r\n");

        ret = f_mkfs("/sd", &fs_para, workbuf, sizeof(workbuf));

        if (ret != FR_OK) {
            LOG_F("fail to make filesystem %d\r\n", ret);
            _CALL_ERROR();
        }

        if (ret == FR_OK) {
            LOG_I("done with formatting.\r\n");
            LOG_I("first start to unmount.\r\n");
            ret = f_mount(NULL, "/sd", 1);
            LOG_I("then start to remount.\r\n");
        }
    }
    else if (ret != FR_OK) {
        LOG_F("fail to mount filesystem,error= %d\r\n", ret);
        LOG_F("SD card might fail to initialise.\r\n");
        _CALL_ERROR();
    }
    else {
        LOG_D("Succeed to mount filesystem\r\n");
    }

    if (ret == FR_OK) {
        LOG_I("FileSystem cluster size:%d-sectors (%d-Byte)\r\n", fs.csize, fs.csize * 512);
    }
}

/**
 * @brief  void queue_task(void* arg)
 * 消息队列循环读取
 * @param arg
*/
static void queue_task(void* arg)
{
    char* ssid = NULL;
    char* password = NULL;
    ssid = flash_get_data(SSID_KEY, 32);
    password = flash_get_data(PASS_KEY, 32);
    if (ssid!=NULL && strlen(ssid) > 0)
    {
        printf("read flash ssid:%s password:%s\r\n", ssid, password);
        wifi_connect(ssid, password);
    }
    else {
        printf("ssid read value is NULL:%06X\r\n", SSID_KEY);
    }
}

int main(void)
{
    //中开启时钟
    board_init();
    // 初始化 存储
    flash_init();

    // 亮绿灯
    gpio = bflb_device_get_by_name("gpio");
    bflb_gpio_init(gpio, GPIO_PIN_14, GPIO_OUTPUT| GPIO_PULLUP | GPIO_SMT_EN | GPIO_DRV_0);
    bflb_gpio_set(gpio, GPIO_PIN_14);

    //设置中断分组
    bflb_irq_set_nlbits(4);
    //设置中断优先级
    bflb_irq_set_priority(37, 3, 0);
    bflb_irq_set_priority(WIFI_IRQn, 1, 0);

    // 拿到 gpio 
    gpio = bflb_device_get_by_name("gpio");
    // 拿到 uart 
    uart0 = bflb_device_get_by_name("uart0");
    shell_init_with_task(uart0);

    // 初始化tcp ip
    tcpip_init(NULL, NULL);
    // 启动WiFi任务
    wifi_start_firmware_task();
    char* ssid = NULL;
    ssid = flash_get_data(SSID_KEY, 32);
    if (ssid!=NULL && strlen(ssid) > 0){
        xTaskCreate(queue_task, "queue task", 1024*6, NULL, 2, NULL);
    }

    // 创建http服务
    create_http_server_task();
    vTaskStartScheduler();
    while (1) {
    }
}
